package com.elaine.factory.alapi;

import com.elaine.constant.AlapiConstant;
import com.elaine.redis.RedisService;
import com.elaine.redis.keymodel.WxPubilcMaterialKey;
import com.elaine.service.WxPbTokenService;
import com.elaine.utils.HttpUtils;
import com.elaine.wxapi.wxpublic.MaterialManagementApi;
import com.elaine.wxapi.wxpublic.response.WxApiResult;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.util.StringUtils;

import java.io.*;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

/**
 * @author wrb
 * @date 2020/3/31 14:34
 */
@Slf4j
public abstract class AlapiFactory {

	public static Map<AlapiConstant, AlapiFactory> factorys = new ConcurrentHashMap<>();

	@Value("${web.upload-path}")
	private String uploadPath;

	@Autowired
	private WxPbTokenService wxPbTokenService;

	@Autowired
	private RedisService redisService;

	/**
	 * 创建工厂对象时，自动注册
	 */
	protected AlapiFactory() {
		registerFactory();
	}

	/**
	 * 把具体工厂注册到map
	 *
	 * @param alapiConstant 文字
	 * @param factory       具体工厂实现类
	 */
	protected void doRegister(AlapiConstant alapiConstant, AlapiFactory factory) {
		factorys.put(alapiConstant, factory);
	}

	/**
	 * 进行注册
	 */
	protected abstract void registerFactory();

	/**
	 * 封装返回的文字消息
	 *
	 * @return
	 */
	public abstract String getReply();

	/**
	 * 获取图片 mediaId
	 *
	 * @param key 图片文件名
	 * @param url 图片获取 url
	 * @return
	 */
	public String getImageMediaIdByKey(String key, String url, String source) {
		//查看 redis 有没有存素材
		String filename = source + "_" + key;
		// TODO 此处可做数据库操作代替 redis
		String mediaId = redisService.get(WxPubilcMaterialKey.token, filename, String.class);
		if (StringUtils.isEmpty(mediaId)) {
			try {
				File file = new File(uploadPath + filename);
				if (!file.exists()) {
					InputStream inputStream = HttpUtils.getInputStreamByRequestGet(url, null, null);
					inputStreamToFile(inputStream, uploadPath + filename);
				}
				String token = wxPbTokenService.getToken();
				WxApiResult wxApiResult = MaterialManagementApi.addImageMaterial(token, uploadPath + filename, filename);
				mediaId = wxApiResult.get("media_id");
				//存入 redis 中
				boolean set = redisService.set(WxPubilcMaterialKey.token, filename, mediaId);
				if (!set) {
					log.error("图片素材id存入redis失败，mediaId：" + mediaId);
				}
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
		return mediaId;
	}

	public void inputStreamToFile(InputStream inputStream, String path) throws IOException {
		int index;
		byte[] bytes = new byte[1024];
		File file = new File(path.substring(0, path.lastIndexOf("/")));
		if (!file.exists()) {
			file.mkdir();
		}

		FileOutputStream downloadFile = new FileOutputStream(path);
		while ((index = inputStream.read(bytes)) != -1) {
			downloadFile.write(bytes, 0, index);
			downloadFile.flush();
		}
		downloadFile.close();
		inputStream.close();

		/*		ByteArrayOutputStream outStream = new ByteArrayOutputStream();
		//创建一个Buffer字符串
		byte[] buffer = new byte[1024];
		//每次读取的字符串长度，如果为-1，代表全部读取完毕
		int len = 0;
		//使用一个输入流从buffer里把数据读取出来
		while ((len = inputStream.read(buffer)) != -1) {
			//用输出流往buffer里写入数据，中间参数代表从哪个位置开始读，len代表读取的长度
			outStream.write(buffer, 0, len);
		}
		//关闭输入流
		inputStream.close();
		//把outStream里的数据写入内存

		//得到图片的二进制数据，以二进制封装得到数据，具有通用性
		byte[] data = outStream.toByteArray();
		//new一个文件对象用来保存图片，默认保存当前工程根目录
		File imageFile = new File(path);
		//创建输出流
		FileOutputStream fileOutStream = new FileOutputStream(imageFile);
		//写入数据
		fileOutStream.write(data);*/
	}
}
